package com.egg.auth.service.role.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.egg.auth.entity.role.Role;
import com.egg.auth.entity.role.RoleLinkUser;
import com.egg.auth.enums.role.RoleAuthCodeEnum;
import com.egg.auth.mapper.role.RoleLinkUserMapper;
import com.egg.auth.service.role.IRoleLinkUserService;
import com.egg.auth.service.role.IRoleService;
import com.egg.common.core.exception.CustomException;
import com.egg.common.mybatis.service.impl.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;


@Service
public class RoleLinkUserServiceImpl extends BaseServiceImpl<RoleLinkUserMapper, RoleLinkUser> implements IRoleLinkUserService {


    @Autowired
    private IRoleService roleService;

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void add(Serializable userId, Serializable roleId) {
        if (ObjectUtil.isEmpty(userId) || ObjectUtil.isEmpty(roleId)) {
            return;
        }
        add(userId, Arrays.asList(roleId));
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void add(Serializable userId, Collection<? extends Serializable> roleId) {
        if (ObjectUtil.isEmpty(userId) || ObjectUtil.isEmpty(roleId)) {
            return;
        }
        List<RoleLinkUser> list = new ArrayList<>();
        roleId.forEach(o -> {
            RoleLinkUser entity = new RoleLinkUser();
            entity.setUserId(Long.parseLong(userId.toString()));
            entity.setRoleId(Long.parseLong(o.toString()));
            list.add(entity);
        });
        baseSave(list);
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void put(Serializable userId, Serializable roleId) {
        if (ObjectUtil.isEmpty(userId) || ObjectUtil.isEmpty(roleId)) {
            return;
        }
        put(userId, Arrays.asList(roleId));
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void put(Serializable userId, Collection<? extends Serializable> roleId) {
        if (ObjectUtil.isEmpty(userId) || ObjectUtil.isEmpty(roleId)) {
            return;
        }
        delByUserId(userId);
        if (ObjectUtil.isEmpty(roleId)) {
            return;
        }
        List<RoleLinkUser> list = new ArrayList<>();
        roleId.forEach(o -> {
            RoleLinkUser entity = new RoleLinkUser();
            entity.setUserId(Long.parseLong(userId.toString()));
            entity.setRoleId(Long.parseLong(o.toString()));
            list.add(entity);
        });
        baseSave(list);
    }

    @Override
    public List<RoleLinkUser> findByUserId(Serializable userId) {
        if (ObjectUtil.isEmpty(userId)) {
            return Collections.emptyList();
        }
        return findByUserId(Collections.singletonList(userId));
    }

    @Override
    public List<RoleLinkUser> findByUserId(Collection<? extends Serializable> userId) {
        if (ObjectUtil.isEmpty(userId)) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<RoleLinkUser> qw = buildLambdaSortQw();
        qw.in(RoleLinkUser::getUserId, userId);
        return list(qw);
    }

    @Override
    public List<RoleLinkUser> findByRoleId(Serializable roleId) {
        if (ObjectUtil.isEmpty(roleId)) {
            return Collections.emptyList();
        }
        return findByRoleId(Collections.singletonList(roleId));
    }

    @Override
    public List<RoleLinkUser> findByRoleId(Collection<? extends Serializable> userId) {
        if (ObjectUtil.isEmpty(userId)) {
            return Collections.emptyList();
        }
        LambdaQueryWrapper<RoleLinkUser> qw = buildLambdaSortQw();
        qw.in(RoleLinkUser::getRoleId, userId);
        return list(qw);
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void delByRoleId(Serializable roleId) {
        if (ObjectUtil.isEmpty(roleId)) {
            return;
        }
        delByRoleId(Collections.singletonList(roleId));
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void delByRoleId(Collection<? extends Serializable> roleId) {
        List<RoleLinkUser> list = findByRoleId(roleId);
        if (ObjectUtil.isEmpty(list)) {
            return;
        }
        baseDel(list.stream().map(o -> o.getId()).collect(Collectors.toSet()));
        list.forEach(o -> {
            StpUtil.logout(o.getUserId());
        });
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void delByUserId(Serializable userId) {
        if (ObjectUtil.isEmpty(userId)) {
            return;
        }
        delByUserId(Collections.singletonList(userId));
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void delByUserId(Collection<? extends Serializable> userId) {
        List<RoleLinkUser> list = findByUserId(userId);
        if (ObjectUtil.isEmpty(list)) {
            return;
        }
        baseDel(list.stream().map(o -> o.getId()).collect(Collectors.toSet()));
        list.forEach(o -> {
            StpUtil.logout(o.getUserId());
        });
    }

    @Transactional(rollbackFor = Throwable.class)
    @Override
    public void initOnApi(Serializable userId) {
        if (ObjectUtil.isEmpty(userId)) {
            return;
        }
        Optional<Role> apiRole = roleService.findByAuthCode(RoleAuthCodeEnum.API.getCode());
        if (!apiRole.isPresent()) {
            throw new CustomException(String.format("请先初始化%s角色", RoleAuthCodeEnum.API.getMessage()));
        }
        add(userId, apiRole.get().getId());
    }


}
